package com.ndp.fb.walle.controller;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.ndp.ec.core.FbUserService;
import com.ndp.ec.core.ProductManageService;
import com.ndp.ec.core.UserService;
import com.ndp.ec.core.model.PlatformType;
import com.ndp.fb.config.ConfigCentre;
import com.ndp.fb.constant.CommonConstants;
import com.ndp.fb.constant.ConfigConst;
import com.ndp.fb.enums.ErrorType;
import com.ndp.fb.enums.connectionobject.ConnectionObjectType;
import com.ndp.fb.enums.customaudience.CustomAudienceSubType;
import com.ndp.fb.exception.BusinessException;
import com.ndp.fb.model.business.bo.adcampaignnamecustomer.AdTitleHistoryBo;
import com.ndp.fb.model.business.bo.result.RegionAndPriceBo;
import com.ndp.fb.model.business.bo.result.RegionAndPriceObjectBo;
import com.ndp.fb.model.business.bo.result.RegionBo;
import com.ndp.fb.model.business.bo.targetingspec.Age;
import com.ndp.fb.model.business.bo.targetingspec.Platform;
import com.ndp.fb.model.business.vo.cache.result.AdPublishConditionDetailCache;
import com.ndp.fb.model.business.vo.cache.result.AdPublishInputHistoryCache;
import com.ndp.fb.model.business.vo.cache.result.AudienceForPublish;
import com.ndp.fb.model.business.vo.cache.result.CustomAudienceCache;
import com.ndp.fb.model.business.vo.cache.result.EntrustAccountVo;
import com.ndp.fb.model.business.vo.cache.result.PageVo;
import com.ndp.fb.model.business.vo.cache.result.PriceLimitBo;
import com.ndp.fb.model.business.vo.cache.result.PublishCache;
import com.ndp.fb.model.business.vo.cache.result.TagName;
import com.ndp.fb.model.business.vo.cache.result.UserAudienceTemplateCache;
import com.ndp.fb.model.business.vo.connectionobject.result.ConnectionObjectVo;
import com.ndp.fb.model.business.vo.productconfiguration.result.ProductConfigurationVo;
import com.ndp.fb.rdb.api.PublishResultRdbService;
import com.ndp.fb.rdb.model.EntrustAccount;
import com.ndp.fb.rdb.model.FbUser;
import com.ndp.fb.rdb.model.Page;
import com.ndp.fb.rdb.model.PublishResult;
import com.ndp.fb.rdb.model.User;
import com.ndp.fb.rdb.model.adpublishcondition.AdPublishConditionDetail;
import com.ndp.fb.rdb.model.adpublishcondition.Region;
import com.ndp.fb.rdb.model.adpublishcondition.RegionAndPrice;
import com.ndp.fb.rdb.model.productmanage.ProductManage;
import com.ndp.fb.redis.api.RedisClient;
import com.ndp.fb.util.DateFormatUtil;
import com.ndp.fb.util.ListUtil;
import com.ndp.fb.util.StringUtil;
import com.ndp.fb.util.thread.CommonThread;
import com.ndp.fb.util.thread.ICallBack;
import com.ndp.fb.util.thread.ThreadExcute;
import com.ndp.fb.walle.business.AdCampNameCustomService;
import com.ndp.fb.walle.business.AdPublishAppAccountCPAService;
import com.ndp.fb.walle.business.AdPublishConditionService;
import com.ndp.fb.walle.business.CacheService;
import com.ndp.fb.walle.business.ConnectionObjectService;
import com.ndp.fb.walle.business.CustomAudienceTemplateService;
import com.ndp.fb.walle.business.PageService;
import com.ndp.fb.walle.business.ProductConfigurationService;
import com.ndp.fb.walle.business.TagForBuildnameService;
import com.ndp.fb.walle.business.UserAudienceTemplateService;
import com.ndp.fb.walle.model.bo.connectionobject.ConnectionObjectBo;
import com.ndp.fb.walle.model.bo.productconfiguration.result.ProductConfigurationBo;
import com.ndp.fb.walle.model.vo.OutputResult;
import com.ndp.fb.walle.model.vo.cache.param.CacheProductVoParam;
import com.ndp.fb.walle.model.vo.cache.param.CacheVoParam;
import com.ndp.fb.walle.model.vo.connectionobject.param.ConnectionObjectVoParam;
import com.ndp.fb.walle.util.BuildCacheUtils;
import com.ndp.fb.walle.util.ConversionUtils;
import com.ndp.fb.walle.util.ResponseUtils;

/**
 * Created by Administrator on 2014/10/24.
 */
@RequestMapping("/cache")
@Controller
public class CacheController {

    private final Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    private PageService pageService;

    @Reference
    private UserService userService;

    @Autowired
    private RedisClient redisClient;

    /**
     * publishBatchService
     */
    @Autowired
    private CacheService cacheService;

    @Autowired
    private ConnectionObjectService connectionObjectService;

    @Autowired
    private ProductConfigurationService productConfigurationService;

    @Autowired
    private AdCampNameCustomService adCampNameCustomService;

    @Reference
    private PublishResultRdbService publishResultRdbServices;

    @Autowired
    private UserAudienceTemplateService userAudienceTemplateService;

    @Autowired
    private CustomAudienceTemplateService customAudienceService;

    @Autowired
    private AdPublishConditionService adPublishConditionService;

    @Reference
    private FbUserService fbUserService;

    @Autowired
    private AdPublishAppAccountCPAService adPublishAppAccountCPAService;

    @Autowired
    private TagForBuildnameService tagForBuildnameService;

    @Reference
    private ProductManageService productManageService;


    private EntrustAccountVo getEntrustAccountVo(EntrustAccount entrustAccount, User user, Long connectionObjectId, Long productConfigurationId) {
        EntrustAccountVo entrustAccountVo = new EntrustAccountVo();
        entrustAccountVo.setId(entrustAccount.getId());
        String displayName = entrustAccount.getEmail() != null ? entrustAccount.getEmail() : (entrustAccount.getName() != null ? entrustAccount.getName() : entrustAccount.getFbAccountId() + "");
        entrustAccountVo.setDisplayName(displayName);
        entrustAccountVo.setFbAccountId(entrustAccount.getFbAccountId());
        entrustAccountVo.setAccountStatus(entrustAccount.getAccountStatus());
        entrustAccountVo.setTimezone(entrustAccount.getTimezone());
        Boolean isSupportCPA = adPublishAppAccountCPAService.isSupportCPA(entrustAccount.getFbAccountId(), productConfigurationId, connectionObjectId);
        entrustAccountVo.setIsSupportCPA(isSupportCPA ? 1 : 0); //设置cpa对该用户可用
        entrustAccountVo.setSupportInstagramAd(entrustAccount.isSupportInstagramAd());
        entrustAccountVo.setFirstSupportInsAct(entrustAccount.getFirstSupportInsAct());
        return entrustAccountVo;
    }

    /**
     * 广告发布-选择完配置之后，获取发布相关数据
     *
     * @param param
     * @param request
     * @return
     */
    @RequestMapping(value = "newProduct")
    @ResponseBody
    public ResponseEntity<String> newProduct(@RequestParam(value = "param", required = true) String param, HttpServletRequest request) {
        logger.info("CacheController newProduct() begin.");
        ErrorType errorType = null;
        PublishCache cache = null;
        try {
            CacheProductVoParam productVoParam = JSON.parseObject(param, CacheProductVoParam.class);
            User user = (User) request.getSession().getAttribute("user");
            List<Page> pages = pageService.getPagesByUserId(user.getTicket());
            if (ListUtil.isNotEmpty(pages)) {
                String cacheId = "publish_cache_key_" + com.ndp.fb.util.UUID.get();
                FbUser fbUser = fbUserService.getFbUser(user.getTicket());
                cache = new PublishCache();
                cache.setCacheId(cacheId);
                String timeZone = user.getTimezoneId();
                cache.setTimeZone(timeZone);
                cache.setFbUserVo(BuildCacheUtils.getFbUserVo(fbUser));
                cache.setUserId(user.getTicket());
                cache.setBeginTime(new Date().getTime());
                cache.setNickName(user.getNickname());

                // 获取产品和产品平台相关信息
                ConnectionObjectVo connectionObjectVo = new ConnectionObjectVo();
                ProductConfigurationVo productConfigurationVo = new ProductConfigurationVo();
                Long productConfigurationId = productVoParam.getProductConfigurationId();
                Long connectionObjectId = productVoParam.getFbConnectionObjectId();
                if (StringUtils.equals(CommonConstants.OUTLINK, productVoParam.getProductType())) {
                    //外链
                    ProductManage productManage
                            = productManageService.findByProductIdAndProductPlatform(connectionObjectId, PlatformType.getPlatformType(productConfigurationId).getPlatform());
                    connectionObjectVo.setId(productManage.getId());
                    connectionObjectVo.setFbConnectionObjectId(productManage.getProdId());
                    connectionObjectVo.setName(productManage.getProdName());
                    connectionObjectVo.setType(2);
                    connectionObjectVo.setProductType(CommonConstants.OUTLINK);

                    productConfigurationVo.setId(productConfigurationId);
                    productConfigurationVo.setFbConnectionObjectId(connectionObjectId);
                    productConfigurationVo.setPlatform(PlatformType.getPlatformType(productConfigurationId).getPlatform());
                    productConfigurationVo.setObjectStoreUrl(productManage.getProdUrl());
                } else {
                    //应用
                    ProductConfigurationBo productConfigurationBo = productConfigurationService.findProductConfigurationById(productConfigurationId);
                    connectionObjectId = productConfigurationBo.getFbConnectionObjectId();
                    ConnectionObjectBo connectionObject = connectionObjectService.findByFbConnectionObjectIdAndType(connectionObjectId, ConnectionObjectType.Application.getType());
                    ConversionUtils.conversion(connectionObject, connectionObjectVo);
                    ConversionUtils.conversion(productConfigurationBo, productConfigurationVo);
                }

                String objective = connectionObjectVo.getName() + "-" + productConfigurationVo.getPlatform();

                List<EntrustAccount> entrustAccounts = adPublishConditionService.findAllowedAccounts(cache.getUserId(), connectionObjectId, productConfigurationId);
                //在这里 去个重
                if (!CollectionUtils.isEmpty(entrustAccounts)) {
                    entrustAccounts = entrustAccounts
                            .stream().collect(Collectors.toSet())
                            .stream().collect(Collectors.toList());
                    List<EntrustAccountVo> entrustAccountVos = new ArrayList<>();
                    for (EntrustAccount entrustAccount : entrustAccounts) {
                        entrustAccountVos.add(this.getEntrustAccountVo(entrustAccount, user, connectionObjectId, productConfigurationVo.getId()));
                    }
                    // add cpa count
                    addCpaCount(entrustAccountVos, connectionObjectId, productConfigurationId);
                    cache.setEntrustAccounts(entrustAccountVos);
                    cache.setObjective(objective);
                    cache.setConnectionObject(connectionObjectVo);
                    cache.setProductConfiguration(productConfigurationVo);

//                    User userAdmin = userService.getAdminUserByCurrentUser(cache.getUserId());
//                    String userAdminId = "";
//                    if (userAdmin != null) {
//                        userAdminId = userAdmin.getTicket();
//                    }
                    //设置广告投放条件检查
                    //String userId, Long connObjId, Long prodCfgId
                    AdPublishConditionDetail adPublishConditionDetail = adPublishConditionService.findDetailById(cache.getUserId(), connectionObjectId, productConfigurationId);
                    List<RegionAndPrice> regionAndPrices = adPublishConditionService.findRegionAndPrice(adPublishConditionDetail.getConditionId());

                    AdPublishConditionDetailCache apcdc = buildAdPublishConditionDetailCache(adPublishConditionDetail, regionAndPrices);
                    cache.setAdPublishConditionDetailCache(apcdc);

                    //page
                    List<Page> boList = getPages(user, adPublishConditionDetail.getPageId());
                    if (ListUtil.isNotEmpty(boList)) {
                        List<PageVo> pageVoList = new ArrayList<>();
                        for (Page page : boList) {
                            PageVo pageVo = new PageVo();
                            try {
                                BeanUtils.copyProperties(pageVo, page);
                            } catch (IllegalAccessException | InvocationTargetException e) {
                                e.printStackTrace();
                            }
                            pageVoList.add(pageVo);
                        }
                        cache.setPageList(pageVoList);
                    }


                    //设置标题历史记录
                    AdPublishInputHistoryCache adPublishInputHistoryCache = adCampNameCustomService.buildAdPublishInputHistoryCache(user.getOrgId(), connectionObjectId, connectionObjectVo.getName());
                    cache.setAdPublishInputHistoryCache(adPublishInputHistoryCache);

                    //v0.8.1 根据应用、配置、使用者初始化用户定位模板 add by sisi
                    UserAudienceTemplateCache userAudienceTemplateCache = userAudienceTemplateService.buildUserAudienceTemplateCache(user.getTicket(), user.getOrgId(), connectionObjectId, productConfigurationId);
                    cache.setUserAudienceTemplate(userAudienceTemplateCache);
                    //v0.8.7 获取账号下的自定义受众
                    List<CustomAudienceCache> accountCustomAudiences = customAudienceService.buildCustomAudienceCachesFBOK(entrustAccounts);
                    cache.setAccountCustomAudiences(accountCustomAudiences);

                    //查询自定义受众和相似受众
                    List<AudienceForPublish> audienceForPublishs = customAudienceService.buildCustomAudienceCaches(entrustAccounts, connectionObjectId);
                    List<AudienceForPublish> customList = audienceForPublishs.stream()
                            .filter(a -> CustomAudienceSubType.CUSTOM.getType().equals(a.getSubtype()))
                            .collect(Collectors.toList());
                    List<AudienceForPublish> lookalikeList= audienceForPublishs.stream()
                            .filter(a -> CustomAudienceSubType.LOOKALIKE.getType().equals(a.getSubtype()))
                            .collect(Collectors.toList());
//                    if (ListUtil.isNotEmpty(audienceForPublishs)) {
//                        for (AudienceForPublish audienceForPublish : audienceForPublishs) {
//                            if (CustomAudienceSubType.CUSTOM.getType().equals(audienceForPublish.getSubtype()))
//                                customList.add(audienceForPublish);
//                            else if (CustomAudienceSubType.LOOKALIKE.getType().equals(audienceForPublish.getSubtype()))
//                                lookalikeList.add(audienceForPublish);
//                        }
//                    }

                    cache.setCustomAudiences(customList);
                    cache.setLookalikeAudiences(lookalikeList);

                    cache.setServerDate(DateFormatUtil.getDateModel(new Date(), "yyyyMMdd", cache.getTimeZone()).getToTimeString());
                    //缓存
                    addTags(cache, connectionObjectId, productConfigurationId, user.getLanguage());

                    cacheService.cache(cacheId, cache, 1, TimeUnit.DAYS);
                } else {
                    // 没有可以使用的广告账号!
                    errorType = ErrorType.ACCOUNT_IS_EMPTY_NEED_CONFIG;
                }
            } else {
                errorType = ErrorType.OBTAIN_PAGE_FAIL;
            }
        } catch (BusinessException e) {
            errorType = ErrorType.LIST_PRODUCT_CONFIGURATION_FAIL;
            logger.error("CacheController product()", e);
            logger.error(e.getMessage(), e);
        } catch (Exception e) {
            errorType = ErrorType.LIST_PRODUCT_CONFIGURATION_FAIL;
            logger.error("CacheController product()", e);
            logger.error(e.getMessage(), e);
        }
        OutputResult outputResult = ResponseUtils.bulidOutputResult(errorType, cache);
        logger.info("CacheController product() end.");
        return ResponseUtils.returnJsonWithUTF8(JSON.toJSONString(outputResult, SerializerFeature.DisableCircularReferenceDetect));
    }

    private void addTags(PublishCache cache, Long appId, Long productConfigurationId, String language) {
        AdPublishConditionDetail adPublishConditionDetail = adPublishConditionService.findDetailById(cache.getUserId(), appId, productConfigurationId);
        if (adPublishConditionDetail != null) {
            cache.getAdPublishConditionDetailCache().setConnObjSimpleName(adPublishConditionDetail.getConnObjSimpleName());
            List<TagName> tagNames =  tagForBuildnameService.buildTagName(language)
                    .stream().filter(t->!(t.getId() == 11L && StringUtil.isEmpty(adPublishConditionDetail.getConnObjSimpleName())))
                    .collect(Collectors.toList());
//            for (TagName tagName : tagForBuildnameService.buildTagName(language)) {
//                if (tagName.getId() == 11L && StringUtil.isEmpty(adPublishConditionDetail.getConnObjSimpleName()))
//                    continue;
//                else {
//                    tagNames.add(tagName);
//                }
//            }
            cache.setTagNames(tagNames);
            Map<String, String> tagVals = tagForBuildnameService.buildTagVal(tagNames, cache);
            cache.setTagVals(tagVals);
            // 构造adCampain使用的标签
            tagForBuildnameService.buildSeq(cache);
        }
    }

    private List<Page> getPages(User user, Long cachePageId) {
        List<Page> boList = new ArrayList<>();
        Long pageId = 0L;
        if (cachePageId != null) {
            pageId = cachePageId;
        }
        Page page = pageService.getPageById(pageId);
        List<Page> pageList = pageService.getPagesByUserId(user.getTicket());
        if (page != null) {
            if (!CollectionUtils.isEmpty(pageList)) {
                for (Page page2 : pageList) {
                    if (page2.getFbPageId().equals(page.getFbPageId())) {
                        boList.add(page);
                    }
                }
            }
            //当前配置的主页已经没有权限了,返回有权限的所有主页
            if (CollectionUtils.isEmpty(boList)) {
                if (!CollectionUtils.isEmpty(pageList)) {
                    boList.addAll(pageList);
                }
            }
        } else {
            //没有配置主页的时候返回所有主页
            if (!CollectionUtils.isEmpty(pageList)) {
                boList.addAll(pageList);
            }
        }
        return boList;
    }


    private List<EntrustAccountVo> addCpaCount(List<EntrustAccountVo> entrustAccounts, Long appId, Long productConfigurationId) {
        List<EntrustAccountVo> accountVoList = new ArrayList<>();
        for (EntrustAccountVo entrustAccount : entrustAccounts) {
            //1、实时更新CPA
            Boolean isSupportCPA = adPublishAppAccountCPAService.isSupportCPA(entrustAccount.getFbAccountId(), productConfigurationId, appId);
            entrustAccount.setIsSupportCPA(isSupportCPA ? 1 : 0); //设置cpa对该用户可用
            //2、实时抓取facebook的营销活动数 多次fetch过程中只会处理一次
            if (!entrustAccount.isDealCount()) {
                //计算publish_result表中各广告账户的数量
                Integer adCampaignCount = 0;
                Integer adSetCount = 0;
                Integer adGroupCount = 0;
                PublishResult publishResult = publishResultRdbServices.searchPublishResultCount(entrustAccount.getFbAccountId());
                if (publishResult != null) {
                    adCampaignCount = publishResult.getAdcampaignCount();
                    adGroupCount = publishResult.getAdgroupCount();
                    adSetCount = publishResult.getAdsetCount();
                }

                //设置每个账号临时汇总
                //从Facebook获取已发送的总数
                Long tempAdCampaignCount = (Long) redisClient.get("FBAdCampCount_" + entrustAccount.getFbAccountId());
                Long tempAdSetCount = (Long) redisClient.get("FBAdSetCount_" + entrustAccount.getFbAccountId());
                Long tempAdGroupCount = (Long) redisClient.get("FBAdGroupCount_" + entrustAccount.getFbAccountId());
                logger.info("-----------------tempAdCampaignCount-------------- " + tempAdCampaignCount);
                logger.info("-----------------tempAdSetCont-------------- " + tempAdSetCount);
                if (tempAdCampaignCount == null) {
                    logger.info(">>>>>>>>>>>>>>>>>>>>>>>>>调用api请求广告账户下adcampaign数量失败");
                    tempAdCampaignCount = 0L;
                }
                if (tempAdSetCount == null) {
                    logger.info(">>>>>>>>>>>>>>>>>>>>>>>>>调用api请求广告账户下adset数量失败");
                    tempAdSetCount = 0L;
                }
                if (tempAdGroupCount == null) {
                    logger.info(">>>>>>>>>>>>>>>>>>>>>>>>>调用api请求广告账户下adGroup数量失败");
                    tempAdGroupCount = 0L;
                }
                entrustAccount.setAdCampaignCount(ConfigCentre.getInteger(ConfigConst.ADCAMPAIGN_THRESHOLD) - adCampaignCount - tempAdCampaignCount.intValue());
                entrustAccount.setAdSetCount(ConfigCentre.getInteger(ConfigConst.ADSET_THRESHOLD) - adSetCount - tempAdSetCount.intValue());
                entrustAccount.setAdGroupCount(ConfigCentre.getInteger(ConfigConst.ADGROUP_THRESHOLD) - adGroupCount - tempAdGroupCount.intValue());
                entrustAccount.setDealCount(true);
            }
            accountVoList.add(entrustAccount);
        }
        return accountVoList;
    }

    @RequestMapping(value = "getAdTitleHistory")
    @ResponseBody
    public ResponseEntity<String> getAdTitleHistory(@RequestParam(value = "param", required = true) String param,
                                                    HttpServletRequest httpServletRequest) {
        logger.info("CacheController getAdTitleHistory() begin.");
        ErrorType errorType = null;
        List<AdTitleHistoryBo> data = null;
        try {
            User user = (User) httpServletRequest.getSession().getAttribute("user");
            ConnectionObjectVoParam paramIn = JSON.parseObject(param, ConnectionObjectVoParam.class);
            data = adCampNameCustomService.getAdTitleHistory(user.getOrgId(), paramIn.getTypeId());
        } catch (Exception e) {
            errorType = ErrorType.INTERNAL_EXCEPTION;
        }

        OutputResult outputResult = ResponseUtils.bulidOutputResult(errorType, data);
        logger.info("CacheController getAdTitleHistory() end.");
        return ResponseUtils.returnJsonWithUTF8(JSON.toJSONString(outputResult));
    }


    /**
     * 广告发布-刷新账号
     *
     * @param param
     * @param request
     * @return
     */
    @RequestMapping(value = "refreshCPAAndAdCampLimit")
    @ResponseBody
    public ResponseEntity<String> refreshCPAAndAdCampLimit(@RequestParam(value = "param", required = true) String param, HttpServletRequest request) {
        logger.info("CacheController refreshCPAAndAdCampLimit() begin.");
        ErrorType errorType = null;
        CacheVoParam cacheVoParam = JSON.parseObject(param, CacheVoParam.class);
        String cacheId = cacheVoParam.getCacheId();
        Map<String, List<EntrustAccountVo>> result = null;
        try {
            final User user = (User) request.getSession().getAttribute("user");
            if (null != cacheId) {
                final PublishCache data = cacheService.fetch(cacheId);
                if (data != null) {
                    List<EntrustAccount> entrustAccounts = adPublishConditionService.findAllowedAccounts(data.getUserId(), data.getConnectionObject().getFbConnectionObjectId(), data.getProductConfiguration().getId());
                    final List<EntrustAccountVo> entrustAccountVos = new ArrayList<>();
                    Set<Long> supportCustomAudienceAccounts = data.getSupportCustomAudienceAccounts();
                    EntrustAccountVo voo;
                    for (EntrustAccount entrustAccount : entrustAccounts) {
                        voo = this.getEntrustAccountVo(entrustAccount, user, data.getConnectionObject().getFbConnectionObjectId(), data.getProductConfiguration().getId());

                        if (CollectionUtils.isEmpty(supportCustomAudienceAccounts) || supportCustomAudienceAccounts.contains(entrustAccount.getFbAccountId())) {
                            voo.setSupportCustomAudience(true);
                            voo.setSupportLookalikeAudience(true);
                        } else {
                            voo.setSupportCustomAudience(false);
                            voo.setSupportLookalikeAudience(false);
                        }
                        entrustAccountVos.add(voo);
                    }
                    //v0.8.7 获取账号下的自定义受众
                    List<CustomAudienceCache> accountCustomAudiences = customAudienceService.buildCustomAudienceCachesFBOK(entrustAccounts);
                    data.setAccountCustomAudiences(accountCustomAudiences);
                    //查询自定义受众和相似受众
                    List<AudienceForPublish> audienceForPublishs = customAudienceService.buildCustomAudienceCaches(entrustAccounts, data.getConnectionObject().getFbConnectionObjectId());
                    List<AudienceForPublish> customList = new ArrayList<>();
                    List<AudienceForPublish> lookalikeList = new ArrayList<>();
                    if (ListUtil.isNotEmpty(audienceForPublishs)) {
                        for (AudienceForPublish audienceForPublish : audienceForPublishs) {
                            if (CustomAudienceSubType.CUSTOM.getType().equals(audienceForPublish.getSubtype()))
                                customList.add(audienceForPublish);
                            else if (CustomAudienceSubType.LOOKALIKE.getType().equals(audienceForPublish.getSubtype()))
                                lookalikeList.add(audienceForPublish);
                        }
                    }
                    data.setCustomAudiences(customList);
                    data.setLookalikeAudiences(lookalikeList);
                    //0.7.5--每次fetch都会抓取最新账号信息
                    if (ListUtil.isNotEmpty(entrustAccountVos)) {
                        final List<EntrustAccountVo> accountVoList = getEntrustAccountFBVos(entrustAccountVos);
                        result = new HashMap<>();
                        result.put("entrustAccounts", accountVoList);
                        data.setEntrustAccounts(accountVoList);
                    } else {
                        logger.info(">>>>>>>>>>>>>>>>>>>>>>>>CacheController refreshCPAAndAdCampLimit()缓存获得EntrustAccounts空");
                        result = new HashMap<>();
                        result.put("entrustAccounts", data.getEntrustAccounts());
                    }
                    cacheService.update(cacheId, data);
                } else {
                    errorType = ErrorType.REDIS_FETCH_FAIL;
                }
            }
        } catch (BusinessException e) {
            logger.error("CacheController refreshCPAAndAdCampLimit():", e);
            logger.error(e.getMessage(), e);
        } catch (Exception e) {
            errorType = ErrorType.INTERNAL_EXCEPTION;
            logger.error(e.getMessage(), e);
        }
        OutputResult outputResult = ResponseUtils.bulidOutputResult(errorType, result);
        logger.info("CacheController refreshCPAAndAdCampLimit() end.");
        return ResponseUtils.returnJsonWithUTF8(JSON.toJSONString(outputResult));
    }

    private List<EntrustAccountVo> getEntrustAccountFBVos(List<EntrustAccountVo> entrustAccountVos) {
        final List<EntrustAccountVo> accountVoList = new ArrayList<>();
        //创建线程池
        ThreadExcute threadExcute = new ThreadExcute();
        for (final EntrustAccountVo entrustAccount : entrustAccountVos) {
            threadExcute.doThread(new CommonThread(new ICallBack() {
                @SuppressWarnings("unchecked")
                @Override
                public <T> void execute(T t) {
                    EntrustAccountVo threadResult = (EntrustAccountVo) t;
                    if (threadResult != null) {
                        accountVoList.add(threadResult);
                    }
                }
            }) {
                @Override
                public void run() {
                    //计算publish_result表中各广告账户的数量
                    Integer adCampaignCount = 0;
                    Integer adSetCount = 0;
                    Integer adGroupCount = 0;
                    PublishResult publishResult = publishResultRdbServices.searchPublishResultCount(entrustAccount.getFbAccountId());
                    if (publishResult != null) {
                        adCampaignCount = publishResult.getAdcampaignCount();
                        adGroupCount = publishResult.getAdgroupCount();
                        adSetCount = publishResult.getAdsetCount();
                    }
                    //设置每个账号临时汇总
                    //从Facebook获取已发送的总数
                    Long tempAdCampaignCount = (Long) redisClient.get("FBAdCampCount_" + entrustAccount.getFbAccountId());
                    Long tempAdSetCount = (Long) redisClient.get("FBAdSetCount_" + entrustAccount.getFbAccountId());
                    Long tempAdGroupCount = (Long) redisClient.get("FBAdGroupCount_" + entrustAccount.getFbAccountId());
                    logger.info("-----------------tempAdCampaignCount-------------- " + tempAdCampaignCount);
                    logger.info("-----------------tempAdSetCont-------------- " + tempAdSetCount);
                    if (tempAdCampaignCount == null) {
                        logger.info(">>>>>>>>>>>>>>>>>>>>>>>>>调用api请求广告账户下adcampaign数量失败");
                        tempAdCampaignCount = 0L;
                    }
                    if (tempAdSetCount == null) {
                        logger.info(">>>>>>>>>>>>>>>>>>>>>>>>>调用api请求广告账户下adset数量失败");
                        tempAdSetCount = 0L;
                    }
                    if (tempAdGroupCount == null) {
                        logger.info(">>>>>>>>>>>>>>>>>>>>>>>>>调用api请求广告账户下adGroup数量失败");
                        tempAdGroupCount = 0L;
                    }
                    entrustAccount.setAdCampaignCount(ConfigCentre.getInteger(ConfigConst.ADCAMPAIGN_THRESHOLD) - adCampaignCount - tempAdCampaignCount.intValue());
                    entrustAccount.setAdSetCount(ConfigCentre.getInteger(ConfigConst.ADSET_THRESHOLD) - adSetCount - tempAdSetCount.intValue());
                    entrustAccount.setAdGroupCount(ConfigCentre.getInteger(ConfigConst.ADGROUP_THRESHOLD) - adGroupCount - tempAdGroupCount.intValue());
                    this.getCallBack().execute(entrustAccount);
                }
            });
        }
        //等待此次线程结束
        threadExcute.waitingTerminated();
        return accountVoList;
    }

    AdPublishConditionDetailCache buildAdPublishConditionDetailCache(AdPublishConditionDetail detail, List<RegionAndPrice> regionAndPrices) {
        AdPublishConditionDetailCache cache = new AdPublishConditionDetailCache();
        cache.setAge(JSON.parseObject(detail.getAge(), Age.class));
        cache.setConnObjSimpleName(detail.getConnObjSimpleName());
        cache.setConditionId(detail.getConditionId());
        cache.setPageId(detail.getPageId());
        //防止null情况json转换前台丢失platform字段
        if (detail != null && detail.getPlatform() != null) {
            cache.setPlatform(JSON.parseArray(detail.getPlatform(), Platform.class));
        } else {
            Platform platform = new Platform();
            List<Platform> list = new ArrayList<>();
            list.add(platform);
            cache.setPlatform(list);
        }
        cache.setPlatform(JSON.parseArray(detail.getPlatform(), Platform.class));
        cache.setPriceLimit(JSON.parseObject(detail.getPriceLimit(), new TypeReference<List<PriceLimitBo>>() {
        }));
        cache.setSex(detail.getSex());

        //设置业务字段
        List<String> includeKeys = new ArrayList<>();
        List<String> excludeKeys = new ArrayList<>();
        List<String> includeValue = new ArrayList<>();
        List<String> excludeValue = new ArrayList<>();
        RegionAndPriceObjectBo o = new RegionAndPriceObjectBo();
        List<RegionAndPriceBo> includeList = new ArrayList<>();
        List<RegionAndPriceBo> excludeList = new ArrayList<>();
        RegionAndPriceBo result;
        if (ListUtil.isNotEmpty(regionAndPrices)) {
            boolean isGlobal = false;
            for (RegionAndPrice bo : regionAndPrices) {
                if (bo.getInclude() != null) {
                    if (bo.getInclude() == 0) {
                        result = new RegionAndPriceBo();
                        result.setConditionId(bo.getConditionId());
                        result.setId(bo.getId());
                        //result.setVpi(bo.getVpi());
                        result.setType(bo.getType());
                        result.setInclude(bo.getInclude());
                        result.setRegion(JSON.parseArray(bo.getRegion(), RegionBo.class));
                        List<Region> regionList = JSON.parseArray(bo.getRegion(), Region.class);
                        if (ListUtil.isNotEmpty(regionList)) {
                            for (Region region : regionList) {
                                excludeKeys.add(region.getKey());
                                excludeValue.add(region.getName());
                            }
                        }
                        excludeList.add(result);
                    } else if (bo.getInclude() == 1 && bo.getType() != null && "global".equals(bo.getType())) {
                        isGlobal = true;
                        cache.setRegionType("global");
                        result = new RegionAndPriceBo();
                        result.setConditionId(bo.getConditionId());
                        result.setId(bo.getId());
                        result.setPrice(bo.getPrice());
                        result.setType(bo.getType());
                        result.setInclude(bo.getInclude());
                        o.setGlobal(result);
                    } else if (bo.getInclude() == 1 && bo.getType() != null && !"global".equals(bo.getType())) {
                        result = new RegionAndPriceBo();
                        result.setConditionId(bo.getConditionId());
                        result.setId(bo.getId());
                        result.setPrice(bo.getPrice());
                        result.setType(bo.getType());
                        result.setInclude(bo.getInclude());
                        result.setRegion(JSON.parseArray(bo.getRegion(), RegionBo.class));
                        List<Region> regionList = JSON.parseArray(bo.getRegion(), Region.class);
                        if (ListUtil.isNotEmpty(regionList)) {
                            for (Region region : regionList) {
                                includeKeys.add(region.getKey());
                                includeValue.add(region.getName());
                            }
                        }
                        includeList.add(result);
                    } else {
                        logger.info("AdPublishConditionController loadDetail() -> transferRegionAndPriceObject : 不匹配！");
                    }
                }
            }
            if (!isGlobal) {
                cache.setRegionType("include");
            }
        }
        o.setExclude(excludeList);
        o.setInclude(includeList);

        cache.setRegionAndPrices(o);
        cache.setKeys(includeKeys);
        cache.setExcludeKeys(excludeKeys);
        cache.setIncludeValue(includeValue);
        cache.setExcludeValue(excludeValue);
        return cache;
    }
}
